home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Info-Mac 4
/
Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso
/
Development
/
Source
/
curses
/
v_doscur.c
< prev
next >
Wrap
Text File
|
1994-05-07
|
12KB
|
489 lines
/*
* Module v_doscur MSDOS-specific video routines
* Author larry gensch, ESQ
*
* Copyright (c) 1987, 1988, 1989
* by Larry Gensch / 104 Lowell Road / Salem, NH 03079
*
* This code may be included in any work, public or private, with the
* exception of creating a commercial curses-compatible subroutine
* library. (In other words, use the code all you want, but please don't
* rip off the author by reselling this code as your own).
*
* If you make modifications to this code (specifically, enhancements that
* are compatible with System V.x curses), please send them to larry gensch at
* the address above to be considered for inclusion in subsequent releases.
* Any machine specific implementation modules (similar to v_doscur.c) for
* other machines are welcomed.
*
* v_doscur.c is a machine-specific driver for curses that writes directly to
* the memory mapped video display. Currently, there is NO support for color
* or routines using PADS (windows larger than the physical terminal screen).
* To port curses to a new machine, this is the module that will have to be
* reimplemented.
*
*/
#include "curses.h"
#include <ctype.h>
#include <stdarg.h>
#include <stdlib.h>
/*
* EXPORT is used to show entry points into this module. Simply grep
* using the pattern '^EXPORT' to list them out.
*/
#ifndef EXPORT
#define EXPORT
#endif
static unsigned GetDS (void);
static void Doinit (int *lines, int *cols);
static void Mapscreen (WINDOW *win);
static void Dispscreen (void);
static void Setcursor (int line, int col);
static void Dosrestore (void);
static bool Kbhit (void);
static int Getkey (bool raw);
/*
* ms_init() - Perform any necessary initializations of the terminal or to
* the implementation module. The LINES and COLS variables should be set
* as well.
*/
EXPORT bool ms_init (void)
{
Doinit(&LINES, &COLS);
return TRUE;
}
/*
* ms_refresh() - Refresh a WINDOW image onto our internal representation
* of our screen. outflag specifies whether or not the actual display
* should be updated. Returns ERR if an error occurred.
*
* Note: If win is NULL, just update the display.
*/
EXPORT int ms_refresh (WINDOW *win, bool outflag)
{
static int Lastcol = 0; /* Save latest cursor position. No provision here for */
static int Lastrow = 0; /* invisible cursor. */
if (win)
Mapscreen(win);
if (win) {
if (! win->_leave) {
Lastrow = _CURS_CURSOR_SCREEN_ROW(win);
Lastcol = _CURS_CURSOR_SCREEN_COL(win);
}
}
if (outflag) {
Dispscreen();
Setcursor(Lastrow, Lastcol);
}
return OK;
}
/*
* ms_end() - Restore the display so that a non-curses application can use
* it. (Restore terminal modes, move cursor to lower left corner, etc.)
*/
EXPORT bool ms_end (void)
{
Setcursor(LINES - 1, 0);
return OK;
}
/*
* ms_restore_scrn() - Allows user to repaint screen as it was before curses initialization.
*/
EXPORT void ms_restore_scrn (void)
{
Dosrestore();
}
/*
* ms_beep() - Sound the workstation alarm. If flag is TRUE, then the
* workstation should be flashed, instead, if possible.
*/
EXPORT void ms_beep (int flag)
{
fputc('\a', stderr);
}
/*
* ms_kbinp() - Get input from keyboard.
*/
EXPORT int ms_kbinp (WINDOW *win, bool raw, bool cbreak)
{
if (win->_nodelay) {
if (! Kbhit())
return ERR;
}
Setcursor(_CURS_CURSOR_SCREEN_ROW(win),
_CURS_CURSOR_SCREEN_COL(win));
return Getkey(raw);
}
/*
* ms_flushinp() - Throw away pending keyboard input.
*/
EXPORT void ms_flushinp (void)
{
while (Kbhit()) getch();
}
/*
* Alternate Character Set table:
*
* Line drawing characters are named as follows:
*
* t
*
* |
* l --+-- r
* |
*
* b
*
* ACS_trbl (t=top, r=right, b=bottom, l=left)
*
* Valid values for each placeholder:
*
* B (blank) S (single) D (double) T (thick)
*
* Curses (currently) only supports B and S.
*/
EXPORT chtype acs_map[256] = {
0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
0x0 , 0x0 , 0x0 , 0x801a, 0x801b, 0x8018, 0x8019, 0x0 ,
0x805b, 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
0x8004, 0x8030, 0x0 , 0x0 , 0x0 , 0x0 , 0x8078, 0x8071,
0x8032, 0x8068, 0x8059, 0x803f, 0x805a, 0x8040, 0x8045, 0x805f,
0x0 , 0x8044, 0x0 , 0x802d, 0x8043, 0x8034, 0x8041, 0x8042,
0x8033, 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x8007, 0x0 ,
};
/* -------------------------------------------- */
/* Private routines and variables */
/* -------------------------------------------- */
static const unsigned Monobase = 0xB000;
static const unsigned Colrbase = 0xB800;
#if defined (__WATCOMC__) && defined (__386__)
# define INT86_FN int386
#else
# define INT86_FN int86
#endif
typedef struct CHAR {
char ch;
char at;
} CHAR;
static CHAR *Screen; /* PC Screen image */
static void *Oldscreen = NULL; /* Saved screen image */
static unsigned Screenbase = 0; /* Segment for OUR machine */
#define VIDEO_INT 0x10 /* Video interrupt */
#define CUR_SIZE 0x1 /* Set cursor size */
#define SET_POSN 0x2 /* Modify cursor posn */
#define GET_POSN 0x3 /* Read current cursor posn */
#define WRITE 0x9 /* Write character */
#define WRITE_TTY 0xe /* Write char & move cursor */
#define GET_VMODE 0xf /* Get video mode & disp pg */
#undef getch /* Defn in conio.h */
#include <dos.h>
#include <string.h>
#include <conio.h>
static union REGS Regs; /* Used to talk to DOS */
static int Xmax = 0; /* Number of columns */
static int Ymax = 0; /* Number of rows */
#define ATTR_NORM 0x07 /* Normal attr *lg* */
#define ATTR_SOUT 0x70 /* Standout attr *lg* */
#define ATTR_UOUT 0x01 /* Underline attr *lg* */
#define ATTR_BOUT 0x80 /* Blinking attr *lg* */
#define ATTR_BOLD 0x08 /* Bold attr *lg* */
#define SCAN_BACKSPACE '\b' /* Backspace key */
#define SCAN_EXIT 0x001B /* Exit key (ESC) */
#define SCAN_CBACKSPACE 0x007F /* Ctrl + Backspace */
#define SCAN_BTAB 0x010F /* Shift + Tab key */
#define SCAN_F1 0x013B /* Function key 1 */
#define SCAN_HOME 0x0147 /* Home key */
#define SCAN_UP 0x0148 /* Up arrow */
#define SCAN_PPAGE 0x0149 /* PgUp key */
#define SCAN_LEFT 0x014B /* Left arrow */
#define SCAN_RIGHT 0x014D /* Right arrow */
#define SCAN_END 0x014F /* End key */
#define SCAN_DOWN 0x0150 /* Down arrow */
#define SCAN_NPAGE 0x0151 /* PgDn key */
#define SCAN_IC 0x0152 /* Ins key */
#define SCAN_DC 0x0153 /* Del key */
#define SCAN_SF1 0x0154 /* Shift + F Key 1 */
#define SCAN_CF1 0x015E /* Ctrl + F Key 1 */
#define SCAN_AF1 0x0168 /* Alt + F Key 1 */
#define SCAN_SLEFT 0x0173 /* Ctrl + Left arrow */
#define SCAN_SRIGHT 0x0174 /* Ctrl + Right arrow */
#define SCAN_SEND 0x0175 /* Ctrl + End key */
#define SCAN_CNPAGE 0x0176 /* Ctrl + PgDn */
#define SCAN_SHOME 0x0177 /* Ctrl + Home key */
#define SCAN_CPPAGE 0x0184 /* Ctrl + PgUp */
/*
* GetDS() - Return the data segment as an unsigned value.
*/
static unsigned GetDS (void)
{
struct SREGS seg;
segread(&seg);
return seg.ds;
}
/*
* Doinit() - Perform our initializations, and set lines and columns.
*/
static void Doinit (int *lines, int *cols)
{
register int i;
CHAR *ptr;
char *src_ptr;
Regs.h.ah = GET_VMODE;
INT86_FN( VIDEO_INT, &Regs, &Regs );
*cols = Xmax = Regs.h.ah;
*lines = Ymax = 25;
if (Screen == NULL)
Screen = (CHAR *)malloc(Xmax * Ymax * sizeof(CHAR));
if (Screen == NULL) {
fputs("v_doscur: memory allocation failure.\n", stderr);
exit(1);
}
for (ptr = Screen, i = *lines * *cols; i >= 0; i--, ptr++) {
ptr->ch = ' ';
ptr->at = ATTR_NORM;
}
if (Regs.h.al == 7)
Screenbase = Monobase;
else
Screenbase = Colrbase;
if (Oldscreen == NULL)
Oldscreen = malloc(Xmax * Ymax * 2);
if (Oldscreen == NULL) {
fputs("v_doscur: memory allocation failure.\n", stderr);
exit(1);
}
#if defined (__WATCOMC__) && defined (__386__)
src_ptr = (Screenbase << 4);
memcpy(Oldscreen, src_ptr, Xmax * Ymax * 2);
#else
movedata(Screenbase, 0, GetDS(), (unsigned) Oldscreen, Xmax * Ymax * 2);
#endif
}
/*
* Mapscreen() - Copy the screen image given to us by CURSES into our
* internal display representation.
*/
static void Mapscreen (WINDOW *win)
{
int maxx, maxy, i_rw, i;
chtype *src_ptr, attr;
CHAR *sptr, *dst_ptr;
if (win->_begy < Ymax && win->_begx < Xmax)
{
dst_ptr = Screen + (win->_begy * Xmax) + win->_begx;
if (win->_flags & _ISPAD)
{
maxx = win->_pmap_maxx - win->_pmap_orgx; /* For pads, get # rows and columns to display. */
maxy = win->_pmap_maxy - win->_pmap_orgy;
src_ptr = win->_y + /* Point to 1st displayed character in pad. */
((win->_pmap_orgy * win->_xdim) +
win->_pmap_orgx);
}
else
{
maxx = win->_maxx;
maxy = win->_maxy;
src_ptr = win->_y;
}
maxy = MIN(maxy, Ymax - win->_begy);
maxx = MIN(maxx, Xmax - win->_begx);
for (i_rw = 0; i_rw < maxy; i_rw++, /* Copy text from window to screen image. */
dst_ptr += Xmax, src_ptr += win->_xdim)
{
for (i = 0; i < maxx; i++)
{
sptr = dst_ptr + i;
attr = *(src_ptr + i) & A_ATTRIBUTES;
sptr->ch = *(src_ptr + i) & A_CHARTEXT;
if (attr & A_ALTCHARSET)
sptr->ch |= 0x80;
sptr->at = ATTR_NORM;
if (attr & A_STANDOUT)
sptr->at = ATTR_SOUT;
if (attr & A_REVERSE)
sptr->at = ATTR_SOUT;
if (attr & A_UNDERLINE)
sptr->at = ATTR_UOUT;
if (attr & A_BOLD)
sptr->at |= ATTR_BOLD;
if (attr & A_BLINK)
sptr->at |= ATTR_BOUT;
}
}
}
}
/*
* Dispscreen() - Make the physical screen look like our internal screen.
*/
static void Dispscreen (void)
{
#if defined (__WATCOMC__) && defined (__386__)
char *src_ptr = (Screenbase << 4);
memcpy(src_ptr, Screen, Xmax * Ymax * 2);
#else
movedata(GetDS(), (unsigned) Screen, Screenbase, 0, Xmax * Ymax * 2);
#endif
}
/*
* Setcursor() - Set the cursor to the specified location.
*/
static void Setcursor (int line, int col)
{
Regs.h.ah = GET_VMODE;
INT86_FN( VIDEO_INT, &Regs, &Regs );
Regs.h.dh = MIN(line, Ymax - 1);
Regs.h.dl = MIN(col, Xmax - 1);
Regs.h.ah = SET_POSN;
INT86_FN(VIDEO_INT, &Regs, &Regs);
}
/*
* Dosrestore() - Restore the screen to what it was before we started()'d
*/
static void Dosrestore (void)
{
if (Oldscreen != NULL)
{
#if defined (__WATCOMC__) && defined (__386__)
char *scr_ptr = (Screenbase << 4);
memcpy(scr_ptr, Oldscreen, Xmax * Ymax * 2);
#else
movedata(GetDS(), (unsigned) Oldscreen, Screenbase, 0, Xmax * Ymax * 2);
#endif
}
}
/*
* Kbhit() - Returns TRUE if a character in the k/b buffer, else FALSE.
*/
static bool Kbhit (void)
{
return kbhit();
}
static int Getkey (bool raw)
{
int c;
if (raw)
return getch();
c = getch();
if (c == 0)
c = getch() | 0x100;
if (c >= SCAN_F1 && c <= SCAN_F1+9)
return KEY_F(c-SCAN_F1+1);
if (c >= SCAN_SF1 && c <= SCAN_SF1+9)
return KEY_F(c-SCAN_SF1+11);
if (c >= SCAN_CF1 && c <= SCAN_CF1+9)
return KEY_F(c-SCAN_CF1+21);
if (c >= SCAN_AF1 && c <= SCAN_AF1+9)
return KEY_F(c-SCAN_AF1+31);
switch (c) {
case SCAN_DOWN: return KEY_DOWN;
case SCAN_UP: return KEY_UP;
case SCAN_LEFT: return KEY_LEFT;
case SCAN_RIGHT: return KEY_RIGHT;
case SCAN_HOME: return KEY_HOME;
case SCAN_BACKSPACE: return KEY_BACKSPACE;
case SCAN_DC: return KEY_DC;
case SCAN_IC: return KEY_IC;
case SCAN_NPAGE: return KEY_NPAGE;
case SCAN_PPAGE: return KEY_PPAGE;
case SCAN_CNPAGE: return KEY_SF;
case SCAN_CPPAGE: return KEY_SR;
case SCAN_BTAB: return KEY_BTAB;
case SCAN_END: return KEY_END;
case SCAN_EXIT: return KEY_EXIT;
case SCAN_SEND: return KEY_SEND;
case SCAN_SHOME: return KEY_SHOME;
case SCAN_SLEFT: return KEY_SLEFT;
case SCAN_SRIGHT: return KEY_SRIGHT;
default:
return c & 0xff;
}
}